package com.panopset.gui.container;

import static com.panopset.Util.SINGLE_SPACE;
import static com.panopset.Util.dspmsg;
import static com.panopset.Util.getCanonicalPath;
import static com.panopset.Util.getParentFrame;
import static com.panopset.Util.log;
import static com.panopset.Util.mkdirs;
import static com.panopset.Util.x;

import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Vector;

import javax.swing.JFileChooser;
import javax.swing.JPanel;
import javax.swing.JTextField;

import com.panopset.app.panopset.Application;
import com.panopset.centralen.util.MathUtil;
import com.panopset.gui.TButton;
import com.panopset.gui.TPanel;

/**
 * File path persistent container.
 *
 * @author Karl Dinwiddie
 *
 */
public class PanFile extends PanField<JPanel> {

    /**
     * Test only.
     *
     * @param s
     *            Not used.
     */
    public static void main(final String... s) {
        new Application() {

            @Override
            protected JPanel createMainPanel() {
                JPanel p = new JPanel();
                p.setLayout(new GridBagLayout());
                GridBagConstraints gbc = new GridBagConstraints();
                gbc.gridx = 2;
                gbc.gridy = 0;
                gbc.fill = GridBagConstraints.HORIZONTAL;
                gbc.weightx = 1.0;
                p.add(new PanFile("test", "testing").getPanel(), gbc);
                p.setBackground(Color.YELLOW);
                return p;
            }
        } .setVisible(true);
    }

    /**
     *
     * @param borderTitle
     *            Border title.
     * @param toolTipText
     *            Tool tip text.
     */
    public PanFile(final String borderTitle, final String toolTipText) {
        this(borderTitle, toolTipText, "");
    }

    /**
     *
     * @param borderTitle
     *            Border title.
     * @param toolTipText
     *            Tool tip text.
     * @param defaultValue
     *            Default value.
     */
    public PanFile(final String borderTitle, final String toolTipText,
            final String defaultValue) {
        this(borderTitle, toolTipText, defaultValue, false);
    }

    /**
     *
     * @param borderTitle
     *            Border title.
     * @param toolTipText
     *            Tool tip text.
     * @param defaultValue
     *            Default value.
     * @param isDirectory
     *            Is directory flag.
     */
    public PanFile(final String borderTitle, final String toolTipText,
            final String defaultValue, final boolean isDirectory) {
        super(borderTitle, toolTipText, defaultValue);
        getPanel().setLayout(new GridLayout(1, 1));
        isDir = isDirectory;
    }

    /**
     * Description.
     */
    private String description = "";

    /**
     * Is directory flag.
     */
    private final boolean isDir;

    /**
     * Update listeners.
     */
    private final Vector<UpdateListener> updateListeners
        = new Vector<UpdateListener>();

    /**
     * Add update listener.
     *
     * @param updateListener
     *            Update listener.
     */
    public final void addUpdateListener(final UpdateListener updateListener) {
        updateListeners.add(updateListener);
    }

    /**
     *
     */
    private void update() {
        for (UpdateListener updateListener : updateListeners) {
            updateListener.update();
        }
    }

    @Override
    public final String getComponentValue() {
        return getFileTextField().getText();
    }

    @Override
    public final void setComponentValue(final String value) {
        getFileTextField().setText(value);
        update();
    }

    /**
     * Set selected file.
     * @param file Selected file.
     */
    public final void setSelectedFile(final File file) {
        if (file != null && file.exists()) {
            getFileTextField().setText(getCanonicalPath(file));
            update();
        }
    }

    /**
     * Get file.
     * @return File.
     */
    public final File getFile() {
        String path = getFileTextField().getText();
        if (path == null) {
            return null;
        }
        if (path.trim().length() == 0) {
            return null;
        }
        return new File(path);
    }

    /**
     * Browse for file.
     */
    final void doBrowse() {
        setSelectedFile(fileDialog(JFileChooser.OPEN_DIALOG));
    }

    /**
     * Create new file.
     */
    final void doNew() {
        setSelectedFile(fileDialog(JFileChooser.SAVE_DIALOG));
        File f = getFile();
        if (f == null || "".equals(getCanonicalPath(f))) {
            dspmsg(x("No file selected."));
            return;
        }
        if (isDir) {
            mkdirs(f);
        } else {
            try {
                FileWriter fw = new FileWriter(f);
                fw.write("");
                fw.flush();
                fw.close();
            } catch (IOException e) {
                log(e);
            }
        }
    }

    /**
     * @param dialogType JFileChooser Dialog type.
     * @return Selected file.
     */
    private File fileDialog(final int dialogType) {
        File rtn = null;
        File dftPath = new File(getCanonicalPath(new File("x")))
                .getParentFile();
        JFileChooser chooser = new JFileChooser();
        if ("".equals(getFileTextField().getText().trim())) {
            if ((dftPath != null) && (getCanonicalPath(dftPath).length() > 0)) {
                chooser.setSelectedFile(dftPath);
            }
        } else {
            chooser.setSelectedFile(getFile());
        }
        if (isDir) {
            chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        } else {
            chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
        }
        chooser.setDialogTitle(getPrompt());
        chooser.setDialogType(JFileChooser.SAVE_DIALOG);
        if (chooser.showOpenDialog(getParentFrame())
                == JFileChooser.APPROVE_OPTION) {
            rtn = chooser.getSelectedFile();
        }
        if (rtn != null) {
            getFileTextField().setText(getCanonicalPath(rtn));
        }
        update();
        return rtn;
    }

    /**
     * @return PanFile panel.
     */
    public final JPanel createGui() {
        return getPanel();
    }

    /**
     * Create component.
     */
    private TPanel panel;

    @Override
    public final TPanel createComponent() {
        String requiredPrompt = null;

        if (isDir) {
            requiredPrompt = x("directory required");
        } else {
            requiredPrompt = x("file required");
        }
        panel = new TPanel.Builder().tip(
                x("Select") + SINGLE_SPACE + description).layout(
                new GridBagLayout()).requiredPrompt(requiredPrompt).construct();

        GridBagConstraints gbc = null;

        TButton btn = new TButton(x("New"), KeyEvent.VK_N, x("Create new")
                + SINGLE_SPACE + description, new ActionListener() {

            public void actionPerformed(final ActionEvent e) {
                doNew();
            }
        });
        gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.weightx = 0;
        panel.add(btn, gbc);
        btn = new TButton(x("Browse"), KeyEvent.VK_B, x("Browse for")
                + SINGLE_SPACE + description, new ActionListener() {
            @Override
            public void actionPerformed(final ActionEvent e) {
                doBrowse();
            }
        });
        gbc = new GridBagConstraints();
        gbc.gridx = 1;
        gbc.gridy = 0;
        gbc.weightx = 0;
        panel.add(btn, gbc);
        gbc = new GridBagConstraints();
        gbc.gridx = 2;
        gbc.gridy = 0;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.weightx = 1.0;

        panel.add(getFileTextField(), gbc);
        return panel;
    }

    /**
     * File text field.
     */
    private JTextField fileTextField;

    /**
     * @return File text field.
     */
    private JTextField getFileTextField() {
        if (fileTextField == null) {
            fileTextField = new JTextField(MathUtil.TEN);
        }
        return fileTextField;
    }

    /**
     * Prompt.
     */
    private String prompt;

    /**
     * @return Prompt.
     */
    private String getPrompt() {
        if (prompt == null) {
            prompt = x("Please select a") + SINGLE_SPACE + createPrompter();
        }
        return prompt;
    }

    /**
     * @return directory or file prompter.
     */
    private String createPrompter() {
        if (isDir) {
            return x("directory");
        } else {
            return x("file");
        }
    }
}
